package com.wl.nio;

import org.junit.Test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Map;
import java.util.Set;

public class TestChannel {
    /**
     * 文件复制（非直接缓冲区）
     * @throws IOException
     */
    @Test
    public void test1() throws IOException {
        FileInputStream fis = null;
        FileOutputStream fos = null;


        FileChannel inChannel = null;
        FileChannel outChannel = null;

        try {
            fis = new FileInputStream("receive.jpg");
            fos = new FileOutputStream("receive2.jpg");

            //获取通道
            inChannel = fis.getChannel();
            outChannel = fos.getChannel();

            //分配指定大小的缓冲区
            ByteBuffer buffer = ByteBuffer.allocate(1024);

            //将通道中的数据存入缓冲区中
            while (inChannel.read(buffer) != -1){
                //切换成读取数据的模式
                buffer.flip();
                //将缓冲区的数据写入通道
                outChannel.write(buffer);
                buffer.clear();
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outChannel != null){
                outChannel.close();
            }
            if (inChannel != null){
                inChannel.close();
            }
            if (fos != null){
                fos.close();
            }
            if (fis != null){
                fis.close();
            }
        }
    }

    /**
     * 文件复制（内存映射文件）
     */
    @Test
    public void test2() throws IOException {
        FileChannel inChannel = FileChannel.open(Paths.get("receive.jpg"), StandardOpenOption.READ);
        FileChannel outChannel = FileChannel.open(Paths.get("receive3.jpg"), StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE_NEW);

        //内存映射文件
        MappedByteBuffer inMapBuffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
        MappedByteBuffer outMapBuffer = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());

        //直接对缓冲区操作
        byte[] dst = new byte[inMapBuffer.limit()];
        inMapBuffer.get(dst);
        outMapBuffer.put(dst);

        if (outChannel != null){
            outChannel.close();
        }
        if (inChannel != null){
            inChannel.close();
        }
    }

    /**
     * 通达之间的数据传输（直接缓冲区）
     * @throws IOException
     */
    @Test
    public void  test3() throws IOException {
        FileChannel inChannel = FileChannel.open(Paths.get("receive.jpg"), StandardOpenOption.READ);
        FileChannel outChannel = FileChannel.open(Paths.get("receive4.jpg"), StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE_NEW);

        inChannel.transferTo(0,inChannel.size(),outChannel);
        //inChannel.transferFrom(inChannel,0,inChannel.size());

        if (outChannel != null){
            outChannel.close();
        }
        if (inChannel != null){
            inChannel.close();
        }
    }

    /**
     * 分散和聚集
     */
    @Test
    public void test4() throws IOException {
        RandomAccessFile raf1 = new RandomAccessFile("1.txt","rw");
        //获取通道
        FileChannel channel1 = raf1.getChannel();
        //分配指定大小的缓冲区
        ByteBuffer buf1 = ByteBuffer.allocate(100);
        ByteBuffer buf2 = ByteBuffer.allocate(1024);

        //分散读取
        ByteBuffer[] bufs = {buf1,buf2};
        channel1.read(bufs);
        for (ByteBuffer byteBuffer: bufs){
            byteBuffer.flip();
        }

        //中文乱码的话可以另存为选择文本的编码方式为UTF-8
        System.out.println(new String(bufs[0].array(),0,bufs[0].limit()));
        System.out.println("============");
        System.out.println(new String(bufs[1].array(),0,bufs[1].limit()));

        RandomAccessFile raf2 = new RandomAccessFile("2.txt","rw");
        FileChannel channel2 = raf2.getChannel();
        channel2.write(bufs);
    }

    @Test
    public void test5(){
        Map<String, Charset> map = Charset.availableCharsets();
        Set<Map.Entry<String,Charset>> set = map.entrySet();
        for (Map.Entry<String, Charset> entry:set){
            System.out.println(entry.getKey()+" = "+entry.getValue());
        }
    }

    @Test
    public void test6() throws IOException {
        Charset charset1 = Charset.forName("GBK");
        //编码器
        CharsetEncoder ce = charset1.newEncoder();
        //解码器
        CharsetDecoder cd = charset1.newDecoder();

        CharBuffer cBuf = CharBuffer.allocate(1024);
        cBuf.put("王磊学习NIO");
        cBuf.flip();

        //编码
        ByteBuffer bBuf= ce.encode(cBuf);
        for (int i = 0;i < bBuf.limit();i++){
            System.out.println(bBuf.get());
        }
        bBuf.flip();
        //解码
        CharBuffer cBuf2 = cd.decode(bBuf);
        System.out.println(cBuf2.toString());
    }

}
